; /////////////////////////////////////////////////////////////////////////////
;
;     This file is part of PurePicBasic.
; 
;     PurePicBasic is free software: you can redistribute it And/Or modify
;     it under the terms of the GNU General Public License As published by
;     the Free Software Foundation, either version 3 of the License, Or
;     (at your option) any later version.
; 
;     PurePicBasic is distributed in the hope that it will be useful,
;     but WITHOUT ANY WARRANTY; without even the implied warranty of
;     MERCHANTABILITY Or FITNESS For A PARTICULAR PURPOSE.  See the
;     GNU General Public License For more details.
; 
;     You should have received a copy of the GNU General Public License
;     along With PurePicBasic.  If Not, see <http://www.gnu.org/licenses/>.
;
; /////////////////////////////////////////////////////////////////////////////

XIncludeFile "helper_functions.pbi"
; XIncludeFile "chipset_instruction.pbi"

; /////////////////////////////////////////////////////////////////////////////
;
; /////////////////////////////////////////////////////////////////////////////
Procedure _get_binary_parameter_size_(string$, index.i)
  
  tmp$ = string$

  For i = 0 To 9
    tmp$ = RemoveString(tmp$,Str(i))
  Next 
  
  idx.i = 1
  p$ = Mid(tmp$,1,1)
  
  For i = 1 To Len(tmp$)
    If idx = index
      ProcedureReturn CountString(tmp$,p$)
    EndIf 
    
    If Mid(tmp$,i,1) <> p$
      idx + 1
    EndIf
    
    p$ = Mid(tmp$,i,1)
  
  Next
EndProcedure

; /////////////////////////////////////////////////////////////////////////////
;
; /////////////////////////////////////////////////////////////////////////////
Procedure.i _count_parameter_(string$)
  
  tmp$ = string$
  
  NewMap param.i()
  
  For i = 0 To 9
    tmp$ = RemoveString(tmp$,Str(i))
  Next 
  
  For i = 1 To Len(tmp$)
    param( Mid(tmp$,i,1) ) + 1
  Next
  
  ProcedureReturn MapSize(param())
EndProcedure

; /////////////////////////////////////////////////////////////////////////////
;
; /////////////////////////////////////////////////////////////////////////////
Procedure.s _get_opcode_(string$)
  
  tmp$ = string$
  

  For i = 0 To 47
    tmp$ = RemoveString(tmp$,Chr(i))
  Next 
  
  For i = 50 To 255
    tmp$ = RemoveString(tmp$,Chr(i))
  Next 
  
  ProcedureReturn tmp$
EndProcedure

; /////////////////////////////////////////////////////////////////////////////
;
; /////////////////////////////////////////////////////////////////////////////
Procedure _parse_chipset_(string$)
    
  string$ = ReplaceString(string$,Chr(13),Chr(10))
  string$ = packString(string$,Chr(10))
  
  string$ = ReplaceString(string$,Chr(9),Chr(32))
  string$ = packString(string$,Chr(32))
  
  NewList lines.s()
  AddElement(lines())
  
  ; Fill file in array
  For i = 1 To Len(string$)
    letter.s = Mid(string$,i,1)
    If letter = Chr(10)
      AddElement(lines())
    Else
      lines() + letter  
    EndIf 
  Next 
  
  
  ; remove comment
  ForEach lines()
    tmp.s = ""
    delete.b = #False 
    For i = 1 To Len(lines() ) 
      letter.s = Mid(lines(),i,1)
      
      If letter = ";"
        delete = #True 
      EndIf 
      
      If delete = #False
        tmp + letter
      EndIf 
    Next 
    lines() = tmp
  Next 
  
  ; remove empty line
  ForEach lines()
    If lines() = ""
      DeleteElement(lines())
    Else
      lines() = ReplaceString(lines(),Chr(32),"$")
    EndIf
  Next 
  
  
  temp_flash_size.i       = 0
  temp_eeprom_size.i      = 0
  temp_ram_size.i         = 0
  temp_memory_bank.i      = 0
  temp_chipset_name.s     = ""
  temp_instruction_name.s = ""
  temp_count_parameters.i = 0
  temp_param_nb.i         = 0
  
  
  
  ForEach lines()
    
    inst$ = StringField(lines(),1,"$")
    
    Select inst$
      Case "FLASH_SIZE"
        temp_flash_size = Val(StringField(lines(),2,"$"))
        
      Case "RAM_SIZE"
        temp_ram_size   =  Val(StringField(lines(),2,"$"))
        
      Case "EEPROM_SIZE"
        temp_eeprom_size   =  Val(StringField(lines(),2,"$"))
        
      Case "MEMORY_BANK"
        temp_memory_bank   =  Val(StringField(lines(),2,"$"))

      Case "CREATE_CHIPSET"
        temp_chipset_name = StringField(lines(),2,"$")
        _create_chipset_(temp_chipset_name,temp_flash_size, temp_ram_size, temp_eeprom_size, temp_memory_bank)
                
        
      Case "INSTRUCTION"
        temp_instruction_name = UCase(StringField(lines(),2,"$"))
        binaryFull$           = StringField(lines(),3,"$")
        temp_count_parameters = _count_parameter_(binaryFull$)
        
        _create_instruction_(temp_instruction_name , _get_opcode_(binaryFull$) , temp_count_parameters, binaryFull$)

        temp_param_nb = 0
        
       Case "PARAMETER"

        binary$ = _get_instruction_binary_full_(temp_instruction_name)
        
        paramIndex.i = Val(StringField(lines(),2,"$")) 
        min.i        = Val(StringField(lines(),3,"$")) 
        max.i        = Val(StringField(lines(),4,"$")) 

        _set_parameter_binary_size_(temp_instruction_name,temp_param_nb, _get_binary_parameter_size_(binary$,temp_param_nb+1))
        _set_parameter_range_(temp_instruction_name,paramIndex,min,max)

        temp_param_nb + 1
        
    EndSelect
    
  Next 
  
  
  
EndProcedure

; /////////////////////////////////////////////////////////////////////////////
;
; /////////////////////////////////////////////////////////////////////////////
Procedure _load_chipset_(fileName$)
  file.i = ReadFile(#PB_Any,fileName$)
  
  If file 
    *buffer = AllocateMemory(Lof(file))
    
    If *buffer <> #Null
      If ReadData(file,*buffer,Lof(file)) <> 0
        _parse_chipset_(PeekS(*buffer))
        FreeMemory(*buffer)
      Else
        PrintN("Error , can't read data from file : " + fileName$)
        End
      EndIf
    Else
      PrintN("Error , can't allocate memory for *buffer")
      End
    EndIf
    CloseFile(file)
  Else
    PrintN("Error , can't read file : " + fileName$)
    End
  EndIf
EndProcedure

; /////////////////////////////////////////////////////////////////////////////
;
; /////////////////////////////////////////////////////////////////////////////
Procedure _parse_chipset_file_()
  directory.i = ExamineDirectory(#PB_Any,"./chipset","*.pic")

  If directory
    While NextDirectoryEntry(directory)
      fileName$ = DirectoryEntryName(directory)
      
      _load_chipset_("./chipset/"+fileName$)
      
    Wend 
    FinishDirectory(directory)
  Else
      PrintN("critical error , chipset directory not found !")
  EndIf 
  
EndProcedure

; IDE Options = PureBasic 5.10 Beta 4 (Windows - x64)
; CursorPosition = 216
; FirstLine = 199
; Folding = --
; EnableXP